﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Net.Mail;
using System.Text;
using System.Net;
using System.Xml;

namespace RegexLib.Web.Models.Web
{
	/// <summary>
	/// 用于发送系统邮件的工具类。
	/// </summary>
	public class RxMailUtility
	{
		/// <summary>
		/// 系统邮件的发件人显示名。
		/// </summary>
		const string ServerDisplayName = "regex-lib.net";

		/// <summary>
		/// 发送一封从Email模板生成的邮件。
		/// </summary>
		/// <param name="template">待发送的模板（发送前请确认已经对主题和正文进行了格式化）。</param>
		/// <param name="address">接收方Email地址。</param>
		public static void SendMailTemplate(
			RxEmailTemplate template,
			string address)
		{
			SendMail(template.Subject, template.Body, ServerDisplayName, address);
		}

		/// <summary>
		/// 发送一封邮件。
		/// </summary>
		/// <param name="subject">邮件主题。</param>
		/// <param name="body">邮件正文（支持HTML）。</param>
		/// <param name="senderDisplayName">发送方的显示名字。</param>
		/// <param name="address">接收方的邮件地址。</param>
		private static void SendMail(
			string subject,
			string body,
			string senderDisplayName,
			string address)
		{
			SmtpClient smtp = CreateSmtpClient();
			RxMailServerConfiguration mailconfig = RxConfigurationSection.Instance.MailServer;

			using (MailMessage msg = new MailMessage())
			{
				msg.Subject = subject;
				msg.Body = body;
				msg.From = new MailAddress(mailconfig.Address, senderDisplayName);
				msg.To.Add(address);

				msg.IsBodyHtml = true;

				Encoding encoding = Encoding.GetEncoding(mailconfig.Encoding);
				msg.SubjectEncoding = encoding;
				msg.BodyEncoding = encoding;

				smtp.Send(msg);
			}
		}

		/// <summary>
		/// 根据web.config中的配置创建SMTP客户端对象。
		/// </summary>
		/// <returns>创建好的SMTP客户端。</returns>
		private static SmtpClient CreateSmtpClient()
		{
			RxMailServerConfiguration mailconfig = RxConfigurationSection.Instance.MailServer;
			SmtpClient smtp = new SmtpClient();
			smtp.Host = mailconfig.Host;
			smtp.Port = mailconfig.Port > 0 ? mailconfig.Port : 25;
			smtp.EnableSsl = mailconfig.EnableSSL;
			smtp.Credentials = new NetworkCredential(mailconfig.UserName, mailconfig.Password);

			return smtp;
		}
	}

	/// <summary>
	/// 表示~/App_Data/EmailTemplates下提供的Email模板。
	/// </summary>
	public class RxEmailTemplate
	{
		/// <summary>
		/// 私有构造器，防止客户端创建实例。
		/// </summary>
		private RxEmailTemplate()
		{
		}

		/// <summary>
		/// 获取Email模板。
		/// </summary>
		/// <param name="name">Email模板的名字，即~/App_Data/EmailTemplates下的配置文件名（不包括.xml扩展名）。</param>
		/// <returns>来自xml文件的Email模板。</returns>
		public static RxEmailTemplate GetTemplate(string name)
		{
			string virtualPath = string.Format("~/App_Data/EmailTemplates/{0}.xml", name);

			XmlDocument xdoc = RxAppDataCache.Get<XmlDocument>(virtualPath);
			if (xdoc == null)
			{
				xdoc = new XmlDocument();
				xdoc.Load(HttpContext.Current.Server.MapPath(virtualPath));
				RxAppDataCache.Set<XmlDocument>(virtualPath, xdoc);
			}

			RxEmailTemplate temp = new RxEmailTemplate()
			{
				Subject = xdoc.SelectSingleNode("/EmailTemplate/Subject").InnerText,
				Body = xdoc.SelectSingleNode("/EmailTemplate/Body").InnerText
			};

			return temp;
		}

		/// <summary>
		/// 用户申请注册时发送的Email模板。
		/// </summary>
		public static RxEmailTemplate Register
		{
			get { return GetTemplate("Register"); }
		}

		/// <summary>
		/// 用户申请修改密码时发送的Email模板。
		/// </summary>
		public static RxEmailTemplate ChangePassword
		{
			get { return GetTemplate("ChangePassword"); }
		}

		/// <summary>
		/// 替换邮件主题中的参数。
		/// </summary>
		/// <param name="args">参数列表，类似于String.Format中的参数。</param>
		public void FormatSubject(params string[] args)
		{
			Subject = string.Format(Subject, args);
		}

		/// <summary>
		/// 替换邮件正文中的参数。
		/// </summary>
		/// <param name="args">参数列表，类似于String.Format中的参数。</param>
		public void FormatBody(params string[] args)
		{
			Body = string.Format(Body, args);
		}

		/// <summary>
		/// 获取邮件主题。
		/// </summary>
		public string Subject
		{
			get;
			private set;
		}

		/// <summary>
		/// 获取邮件正文。
		/// </summary>
		public string Body
		{
			get;
			private set;
		}
	}
}
